/**
 * 
 */
package pl.edu.agh.winmon.widget;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;

import pl.edu.agh.winmon.hibernate.Process;
import pl.edu.agh.winmon.hibernate.ProcessStatEntry;
import pl.edu.agh.winmon.hibernate.Turn;

/**
 * This widget provides memory info.
 * 
 * @author kret
 */
public class ProcessDetailDialog extends Composite {

	private Process process;

	private TabFolder tabs;

	private Label cpuValue;

	private Label threadsValue;

	private Label memoryValue;

	private Label virtualMemoryValue;

	private Label systemTimeValue;

	private Label userTimeValue;

	private Label fdValue;

	private Combo turnCombo;

	private Map<String, Turn> turnMap = new HashMap<String, Turn>();

	/**
	 * Constructor.
	 * 
	 * @param parent
	 *            parent composite
	 */
	public ProcessDetailDialog(Shell parent, Process process) {
		super(parent, SWT.NONE);
		this.process = process;
		setLayout(new GridLayout(2, false));
		createControls();
	}

	private void createTurnPicker(Composite parent) {
		Label screenshotDate = new Label(parent, SWT.NONE);
		screenshotDate.setText("Choose system snapshot");

		turnCombo = new Combo(parent, SWT.NONE);
		turnCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));

		for (ProcessStatEntry processStatEntry : process.getStatEntries()) {
			if (processStatEntry != null && processStatEntry.getTurn() != null) {
				turnCombo.add(new Date(processStatEntry.getTurn()
						.getStartTime()).toString());
				turnCombo.setData(new Date(processStatEntry.getTurn()
						.getStartTime()).toString(), processStatEntry);
			}
		}
		turnCombo.select(0);
		turnCombo.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent arg0) {
				updateTurnData();
			}
		});
	}

	private void createResourceInfo() {

		Composite resourcesComposite = new Composite(tabs, SWT.NONE);
		resourcesComposite.setLayout(new GridLayout(2, true));

		TabItem cpuItem = new TabItem(tabs, SWT.NONE);
		cpuItem.setControl(resourcesComposite);
		cpuItem.setText("Resources");

		Label label = new Label(resourcesComposite, SWT.NONE);
		label.setText("Active threads");
		label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		threadsValue = new Label(resourcesComposite, SWT.NONE);
		threadsValue.setText("");

		label = new Label(resourcesComposite, SWT.NONE);
		label.setText("File descriptors");

		fdValue = new Label(resourcesComposite, SWT.NONE);
		fdValue.setText("");

		label = new Label(resourcesComposite, SWT.NONE);
		label.setText("Total resident memory");

		memoryValue = new Label(resourcesComposite, SWT.NONE);
		memoryValue.setText("");

		label = new Label(resourcesComposite, SWT.NONE);
		label.setText("Total virtual memory");

		virtualMemoryValue = new Label(resourcesComposite, SWT.NONE);
		virtualMemoryValue.setText("");

	}

	private void createTimeInfo() {
		Composite timeComposite = new Composite(tabs, SWT.NONE);
		timeComposite.setLayout(new GridLayout(2, true));

		TabItem global = new TabItem(tabs, SWT.NONE);
		global.setControl(timeComposite);
		global.setText("CPU info");

		Label label = new Label(timeComposite, SWT.NONE);
		label.setText("CPU usage");
		label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		cpuValue = new Label(timeComposite, SWT.NONE);
		cpuValue.setText("");

		label = new Label(timeComposite, SWT.NONE);
		label.setText("Kernel CPU time");
		label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		systemTimeValue = new Label(timeComposite, SWT.NONE);
		systemTimeValue.setText("");

		label = new Label(timeComposite, SWT.NONE);
		label.setText("User CPU time");
		label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		userTimeValue = new Label(timeComposite, SWT.NONE);
		userTimeValue.setText("");

	}

	private void createGlobalInfo() {
		Composite globalComposite = new Composite(tabs, SWT.NONE);
		globalComposite.setLayout(new GridLayout(2, true));

		TabItem global = new TabItem(tabs, SWT.NONE);
		global.setControl(globalComposite);
		global.setText("Global info");

		Label label = new Label(globalComposite, SWT.NONE);
		label.setText("PID");
		label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		Label value = new Label(globalComposite, SWT.NONE);
		value.setText(process.getPid().toString());

		label = new Label(globalComposite, SWT.NONE);
		label.setText("Program name");

		value = new Label(globalComposite, SWT.NONE);
		value.setText(process.getProgram().getName());

		label = new Label(globalComposite, SWT.NONE);
		label.setText("Start date and time");

		value = new Label(globalComposite, SWT.NONE);
		value.setText(new Date(process.getStartTime()).toString());
	}

	private void createControls() {
		createTurnPicker(this);
		tabs = new TabFolder(this, SWT.NONE);

		GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
		gd.horizontalSpan = 2;

		tabs.setLayoutData(gd);
		createGlobalInfo();
		createResourceInfo();
		createTimeInfo();
		updateTurnData();
	}

	private void updateTurnData() {
		ProcessStatEntry processStatEntry = (ProcessStatEntry) turnCombo
				.getData(turnCombo.getText());

		cpuValue.setText(processStatEntry.getCpuUsage().toString());
		memoryValue.setText(processStatEntry.getTotalResidentMemory()
				.toString());
		virtualMemoryValue.setText(processStatEntry.getTotalVirtualMemory()
				.toString());
		threadsValue.setText(processStatEntry.getActiveThreads().toString());
		systemTimeValue.setText(processStatEntry.getCpuKernelTime().toString());
		userTimeValue.setText(processStatEntry.getCpuUserTime().toString());
		fdValue.setText(processStatEntry.getFileDescriptors().toString());
	}
}
